﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using AgnisEbmtTranslator.DataSets;
using System.Data;
using System.Collections;
using System.Windows.Forms;
using AgnisEbmtTranslator.Custom_Controls;

namespace AgnisEbmtTranslator
{
    #region TRANSLATION
    /// <summary>
    /// Main translation class providing the methods used to translate data.
    /// </summary>
    public class TranslatorProcess
    {
        #region Local members declaration

        static string textReport;
        static string textReport2;
        static MappingDataSet dsMappingInfo = new MappingDataSet();
        //Original dataset.
        public DataSet dsEbmtPatientG = new DataSet();
        //Filtered dataset.
        public DataSet dsFilteredEbmtPatientG;
        //Main IDs for treatment:
        public int patientID;
        public int patientIDAA;
        public DateTime dateOfTransplant;
        private AgnisForm2450DuePeriods currentAgnisFormDuePeriod;
        public enum AgnisForm2450DuePeriods
        {
            Null = 0,
            HundredDays = 1,
            SixtMonths = 2,
            Annual = 3
        }




        #endregion

        #region Constructor

        public TranslatorProcess(String ebmtConnectionString, String mappingInfoConnectionString)
        {
            EbmtDAL.EbmtDAL.SetCurrentEbmtDbConnectionString(ebmtConnectionString);
            MappingInfoDAL.SetCurrentMappingInfoConnectionString(mappingInfoConnectionString);
            //We load the mapping information for this form.
            MappingInfoDAL.LoadMappingInfo(dsMappingInfo);
            //We load the structure information for the agnis_forms.
            MappingInfoDAL.LoadAgnisFormsInfo(dsMappingInfo);
        }
        #endregion

        #region Methods to call the translation process
        /// <summary>
        /// Generates an Agnis form for a given EBMT Patient.
        /// </summary>
        /// <param name="ebmtPatientID">The EBMT patient's Center ID</param>
        /// <param name="ebmtPatientIDAA">The EBMT patient's ID on this center.</param>
        /// <param name="ebmtDateOfTransplant">The date of transplant.</param>
        /// <param name="agnisPaperFormNumber">The AGNIS paper form number.</param>
        /// <param name="agnisFormPublicID">The AGNIS form Public ID.</param>
        /// <param name="agnisFormVersion">The AGNIS form version.</param>
        /// <param name="agnisFormDuePeriod">The AGNIS form due period.</param>
        /// <param name="instanceId">Form instance Id</param>
        /// <returns>An AGNIS FormRevision object</returns>
        public AgnisDAL.ServiceAgnis.FormRevision GenerateAgnisFormForPatient(int ebmtPatientID, int ebmtPatientIDAA, DateTime ebmtDateOfTransplant, int agnisPaperFormNumber, int agnisFormPublicID, decimal agnisFormVersion, AgnisForm2450DuePeriods agnisFormDuePeriod, string instanceId)
        {
            EbmtDAL.EbmtDAL.recordsSelectionsList.Clear();
            switch (agnisPaperFormNumber)
            {
                case 2400: //Paper Form number for Pre-TED form.
                    if (ebmtPatientID > 0 && ebmtPatientIDAA > 0 &&
                        ebmtDateOfTransplant > DateTime.MinValue &&
                        agnisFormPublicID > 0 &&
                        agnisFormVersion > 0)
                    {
                        return GenerateForm2400(ebmtPatientID, ebmtPatientIDAA, ebmtDateOfTransplant, agnisFormPublicID, agnisFormVersion, instanceId);
                    }
                    else
                    {
                        throw new TranslationException("One or more of the arguments are not valid.");
                    }
                case 2450: //Paper Form number for Post-TED form.
                    if (ebmtPatientID > 0 && ebmtPatientIDAA > 0 &&
                        ebmtDateOfTransplant > DateTime.MinValue &&
                        agnisFormDuePeriod != AgnisForm2450DuePeriods.Null &&
                        agnisFormPublicID > 0 &&
                        agnisFormVersion > 0)
                    {
                        return GenerateForm2450(ebmtPatientID, ebmtPatientIDAA, ebmtDateOfTransplant, agnisFormPublicID, agnisFormVersion, agnisFormDuePeriod, instanceId);
                    }
                    else
                    {
                        throw new TranslationException("One or more of the arguments are not valid.");
                    }
                case 2900: //Paper Form number for ....
                    if (ebmtPatientID > 0 && ebmtPatientIDAA > 0 &&
                        agnisFormPublicID > 0 &&
                        agnisFormVersion > 0)
                    {
                        return GenerateForm2900(ebmtPatientID, ebmtPatientIDAA, ebmtDateOfTransplant, agnisFormPublicID, agnisFormVersion, instanceId);
                    }
                    else
                    {
                        throw new TranslationException("One or more of the arguments are not valid.");
                    }
                default:
                    return null;
            }
        }

        #region Form 2450 generation

        /// <summary>
        /// Generate a new Agnis Form 2450 Post-TED form, for an EBMT patient passed as parameter.
        /// </summary>
        /// <param name="ebmtPatientID">The EBMT patient ID (center id owning this patient)</param>
        /// <param name="ebmtPatientIDAA">The EBMT patient IDAA</param>
        /// <param name="ebmtDateOfTransplant">The date of transplant</param>
        /// <param name="agnisFormPublicID">The Agnis Form Public ID</param>
        /// <param name="agnisFormVersion">The Agnis Form Version Number</param>
        /// <param name="agnisFormDuePeriod">The due period (100days, 6month or annual issue)</param>
        /// <param name="isForUpdate">Indicate either it is for an update submitting</param>
        /// <returns>An AGNIS FormRevision object.</returns>
        public AgnisDAL.ServiceAgnis.FormRevision GenerateForm2450(int ebmtPatientID, int ebmtPatientIDAA, DateTime ebmtDateOfTransplant, int agnisFormPublicID, decimal agnisFormVersion, AgnisForm2450DuePeriods agnisFormDuePeriod, string instanceId)
        {
            currentAgnisFormDuePeriod = agnisFormDuePeriod;
            switch (agnisFormDuePeriod)
            {
                case AgnisForm2450DuePeriods.HundredDays:
                    return GenerateHundredDayForm2450(ebmtPatientID, ebmtPatientIDAA, ebmtDateOfTransplant, agnisFormPublicID, agnisFormVersion, instanceId);
                case AgnisForm2450DuePeriods.SixtMonths:
                    return GenerateSixtMonthForm2450(ebmtPatientID, ebmtPatientIDAA, ebmtDateOfTransplant, agnisFormPublicID, agnisFormVersion);
                case AgnisForm2450DuePeriods.Annual:
                    return GenerateAnnualForm2450(ebmtPatientID, ebmtPatientIDAA, ebmtDateOfTransplant, agnisFormPublicID, agnisFormVersion);
                default:
                    return null;
            }
        }

        /// <summary>
        ///  Generate a new Agnis Form 2450 Post-TED form for the hundred days report, for an EBMT patient passed as parameter.
        /// </summary>
        /// <param name="ebmtPatientID">The EBMT patient ID (center id owning this patient)</param>
        /// <param name="ebmtPatientIDAA">The EBMT patient IDAA</param>
        /// <param name="ebmtDateOfTransplant">The date of transplant</param>
        /// <param name="agnisFormPublicID">The Agnis Form Public ID</param>
        /// <param name="agnisFormVersion">The Agnis Form Version Number</param>
        /// <returns>An AGNIS FormRevision object.</returns>
        public AgnisDAL.ServiceAgnis.FormRevision GenerateHundredDayForm2450(int ebmtPatientID, int ebmtPatientIDAA, DateTime ebmtDateOfTransplant, int agnisFormPublicID, decimal agnisFormVersion, string instanceID)
        {
            //We load the patient ebmt data.
            patientID = ebmtPatientID;
            patientIDAA = ebmtPatientIDAA;
            dateOfTransplant = ebmtDateOfTransplant;
            dsEbmtPatientG = EbmtDAL.EbmtDAL.LoadPatientData(ebmtPatientID, ebmtPatientIDAA);
            //We initialize the objects used to create different patient data views.
            EbmtDAL.EbmtDAL.InitializePatientDataBindingSourcesG(dsEbmtPatientG);
            //We execute the translation process.
            return TranslateToAgnisForm(agnisFormPublicID, agnisFormVersion, instanceID);
        }

        /// <summary>
        ///  Generate a new Agnis Form 2450 Post-TED form for the 6 months report, for an EBMT patient passed as parameter.
        /// </summary>
        /// <param name="ebmtPatientID">The EBMT patient ID (center id owning this patient)</param>
        /// <param name="ebmtPatientIDAA">The EBMT patient IDAA</param>
        /// <param name="ebmtDateOfTransplant">The date of transplant</param>
        /// <param name="agnisFormPublicID">The Agnis Form Public ID</param>
        /// <param name="agnisFormVersion">The Agnis Form Version Number</param>
        /// <param name="isForUpdate">Indicate either it is for an update submitting</param>
        /// <returns>An AGNIS FormRevision object.</returns>
        public AgnisDAL.ServiceAgnis.FormRevision GenerateSixtMonthForm2450(int ebmtPatientID, int ebmtPatientIDAA, DateTime ebmtDateOfTransplant, int agnisFormPublicID, decimal agnisFormVersion)
        {
            //TODO: This Form issue needs still to be developed.
            return null;
        }

        /// <summary>
        ///  Generate a new Agnis Form 2450 Post-TED form for the annual report, for an EBMT patient passed as parameter.
        /// </summary>
        /// <param name="ebmtPatientID">The EBMT patient ID (center id owning this patient)</param>
        /// <param name="ebmtPatientIDAA">The EBMT patient IDAA</param>
        /// <param name="ebmtDateOfTransplant">The date of transplant</param>
        /// <param name="agnisFormPublicID">The Agnis Form Public ID</param>
        /// <param name="agnisFormVersion">The Agnis Form Version Number</param>
        /// <param name="isForUpdate">Indicate either it is for an update submitting</param>
        /// <returns>An AGNIS FormRevision object.</returns>
        public AgnisDAL.ServiceAgnis.FormRevision GenerateAnnualForm2450(int ebmtPatientID, int ebmtPatientIDAA, DateTime ebmtDateOfTransplant, int agnisFormPublicID, decimal agnisFormVersion)
        {
            //TODO: This Form issue needs still to be developed.
            return null;
        }
        #endregion

        #region Form 2900 generation

        /// <summary>
        /// Generates a 2900 Form for the patient passed as parameter.
        /// </summary>
        /// <param name="ebmtPatientID">The EBMT patient's Center ID</param>
        /// <param name="ebmtPatientIDAA">The EBMT patient's ID on this center.</param>
        /// <param name="agnisFormPublicID">The AGNIS form Public ID.</param>
        /// <param name="agnisFormVersion">The AGNIS form version.</param>
        /// <param name="isForUpdate">Indicates either it is a generation for an update submition</param>
        /// <returns>An AGNIS FormRevision object</returns>
        public AgnisDAL.ServiceAgnis.FormRevision GenerateForm2900(int ebmtPatientID, int ebmtPatientIDAA, DateTime ebmtDateOfTransplant, int agnisFormPublicID, decimal agnisFormVersion, string instanceID)
        {
            //We load the patient ebmt data.
            patientID = ebmtPatientID;
            patientIDAA = ebmtPatientIDAA;
            dateOfTransplant = ebmtDateOfTransplant;
            dsEbmtPatientG = EbmtDAL.EbmtDAL.LoadPatientData(ebmtPatientID, ebmtPatientIDAA);
            //We initialize the objects used to create different patient data views.
            EbmtDAL.EbmtDAL.InitializePatientDataBindingSourcesG(dsEbmtPatientG);
            //We execute the translation process.
            return TranslateToAgnisForm(agnisFormPublicID, agnisFormVersion, instanceID);
        }
        #endregion

        #region Form 2400 generation

        /// <summary>
        /// Generates a 2400 AGNIS form for the patient passed as parameter.
        /// </summary>
        /// <param name="ebmtPatientID">The EBMT patient's Center ID</param>
        /// <param name="ebmtPatientIDAA">The EBMT patient's ID on this center.</param>
        /// <param name="ebmtDateOfTransplant">The date of transplant.</param>
        /// <param name="agnisFormPublicID">The AGNIS form Public ID.</param>
        /// <param name="agnisFormVersion">The AGNIS form version.</param>
        /// <param name="instanceId">Form instance Id</param>
        /// <returns></returns>
        public AgnisDAL.ServiceAgnis.FormRevision GenerateForm2400(int ebmtPatientID, int ebmtPatientIDAA, DateTime ebmtDateOfTransplant, int agnisFormPublicID, decimal agnisFormVersion, string instanceId)
        {
            //We load the patient ebmt data.
            patientID = ebmtPatientID;
            patientIDAA = ebmtPatientIDAA;
            dateOfTransplant = ebmtDateOfTransplant;
            dsEbmtPatientG = EbmtDAL.EbmtDAL.LoadPatientData(ebmtPatientID, ebmtPatientIDAA);
            //We initialize the objects used to create different patient data views.
            EbmtDAL.EbmtDAL.InitializePatientDataBindingSourcesG(dsEbmtPatientG);
            //We execute the translation process.
            return TranslateToAgnisForm(agnisFormPublicID, agnisFormVersion, instanceId);
        }
        #endregion
        #endregion

        #region Translation process methods.

        /// <summary>
        /// Instanciate an Agnis object, then
        /// Generate an XML report file format
        /// </summary>
        /// <param name="formPublicID"></param>
        /// <param name="formVersion"></param>
        private AgnisDAL.ServiceAgnis.FormRevision TranslateToAgnisForm(int formPublicID, decimal formVersion, string instanceId)
        {
            //We create the Agnis required objects and we filled them out.
            textReport = "";
            textReport2 = "";
            AgnisDAL.ServiceAgnis.Form newAgnisForm = MappingInfoDAL.aForm;
            newAgnisForm.publicId = formPublicID;
            newAgnisForm.version = formVersion;
            newAgnisForm.publicIdSpecified = true;
            newAgnisForm.versionSpecified = true;
            newAgnisForm.originator = new AgnisDAL.ServiceAgnis.Institution();
            newAgnisForm.originator.uniqueName = "cibmtr_center_number:10186";
            newAgnisForm.instanceId = instanceId;

            AgnisDAL.ServiceAgnis.FormRevision newAgnisFormRevision = MappingInfoDAL.aFormRevision;
            newAgnisFormRevision.form = newAgnisForm;
            //This following list is the list of module INSTANCES in the form.
            //Meaning that the same Module PublicID could be repeated in the range limited by the column "[Module Max Repeat]"
            //wich is the maximum number of instances for a module starting on zero.
            List<AgnisDAL.ServiceAgnis.Module> modulesCollection = new List<AgnisDAL.ServiceAgnis.Module>();
            //This dataview is going to give us the list of modules belonging to this form with the information of
            //the number of instances allowed for each module.
            DataView dvModulesList = MappingInfoDAL.GetModulesListForThisForm(dsMappingInfo, formPublicID, formVersion);
            if (dvModulesList != null)
            {
                //RRA  : adding a first module at the beginning              
                if (instanceId != "") //instance_id is not null in an update case
                {
                    List<AgnisDAL.ServiceAgnis.Module> resultSingleModInstancesList = UpdateProcessModule(instanceId);
                    if (resultSingleModInstancesList.Count > 0)
                    {
                        foreach (AgnisDAL.ServiceAgnis.Module SingleModuleIns in resultSingleModInstancesList)
                        {
                            modulesCollection.Add(SingleModuleIns);
                        }
                    }
                }
                foreach (DataRowView moduleRowView in dvModulesList)
                {
                    //For each module information in this list we process the module and return a list of modules instances
                    //corresponding to the modules instances generated by this process (in the limits of "[Module Max Repeat]")
                    MappingDataSet.ModulesListRow moduleRow = (MappingDataSet.ModulesListRow)moduleRowView.Row;
                    List<AgnisDAL.ServiceAgnis.Module> resultModInstancesList = ProcessModule(moduleRow);
                    if (resultModInstancesList.Count > 0)
                    {
                        foreach (AgnisDAL.ServiceAgnis.Module moduleIns in resultModInstancesList)
                        {
                            modulesCollection.Add(moduleIns);
                        }
                    }
                }

                textReport = textReport + "List of Records Selections ID backed up:" + "\r\n";
                foreach (EbmtDAL.RecordSelectionMem rItem in EbmtDAL.EbmtDAL.recordsSelectionsList)
                {
                    textReport = textReport + "Record Selection ID: " + rItem.RecordSelectionId + "\r\n";
                }

                newAgnisFormRevision.moduleCollection = modulesCollection.ToArray<AgnisDAL.ServiceAgnis.Module>();
                string xmlOutput = SerializeObjectToXmlString(newAgnisFormRevision);
                string fileName = AgnisEbmtTranslator.Properties.Settings.Default.AgnisTranslatedFormOutputDir + "/patID_ID_patIDAA_IDAA_transplant_tDate_form_PublicID_XXXX_output.xml";
                string rptFileName = AgnisEbmtTranslator.Properties.Settings.Default.AgnisTranslatedFormOutputDir + "/patID_ID_patIDAA_IDAA_transplant_tDate_form_PublicID_XXXX_report.txt";
                string rptFileName2 = AgnisEbmtTranslator.Properties.Settings.Default.AgnisTranslatedFormOutputDir + "/patID_ID_patIDAA_IDAA_form_PublicID_XXXX_report2.txt";
                fileName = fileName.Replace("_XXXX_", "_" + formPublicID + "_");
                fileName = fileName.Replace("_ID_", "_" + patientID + "_");
                fileName = fileName.Replace("_IDAA_", "_" + patientIDAA + "_");
                fileName = fileName.Replace("_tDate_", "_" + dateOfTransplant.ToShortDateString().Replace("/", "-") + "_");
                rptFileName = rptFileName.Replace("_XXXX_", "_" + formPublicID + "_");
                rptFileName = rptFileName.Replace("_ID_", "_" + patientID + "_");
                rptFileName = rptFileName.Replace("_IDAA_", "_" + patientIDAA + "_");
                rptFileName = rptFileName.Replace("_tDate_", "_" + dateOfTransplant.ToShortDateString().Replace("/", "-") + "_");
                rptFileName2 = rptFileName2.Replace("_XXXX_", "_" + formPublicID + "_");
                rptFileName2 = rptFileName2.Replace("_ID_", "_" + patientID + "_");
                rptFileName2 = rptFileName2.Replace("_IDAA_", "_" + patientIDAA + "_");
                StreamWriter sWriter = new StreamWriter(fileName, false);
                StreamWriter sWriter2 = new StreamWriter(rptFileName, false);
                StreamWriter sWriter3 = new StreamWriter(rptFileName2, false);
                sWriter.Write(xmlOutput);
                sWriter2.Write(textReport);
                sWriter3.Write(textReport2);
                sWriter.Close();
                sWriter2.Close();
                sWriter3.Close();
                return newAgnisFormRevision;
            }
            else
            {
                throw new TranslationException("The function GetFormModulesList has returned an invalid value");
            }
        }

        #region Filling Agnis objects.

        /// <summary>
        /// Process the module passed as parameter.
        /// It calls the AssembleModuleInstances method in order to return a List of module instances for the module.
        /// </summary>
        /// <param name="moduleRow"></param>
        /// <returns></returns>
        private List<AgnisDAL.ServiceAgnis.Module> ProcessModule(MappingDataSet.ModulesListRow moduleRow)
        {
            textReport = textReport + "___________________________________________________________________________________" + "\r\n";
            textReport = textReport + "Processing Module Public ID: " + moduleRow.Module_Public_ID + "\r\n";
            textReport = textReport + "Normalized Module: " + moduleRow.Normalized + "\r\n";
            return AssembleModuleInstances(moduleRow);
        }
        ///RRA submition for update
        private List<AgnisDAL.ServiceAgnis.Module> UpdateProcessModule(string instance_id)
        {
            return UpdateModuleInstances(instance_id);
        }

        /// <summary>
        /// Assembles the list of instances for this module.
        /// Generates a List of Agnis Module objects.
        /// </summary>
        /// <param name="moduleRow"></param>
        /// <returns>moduleIntances</returns>
        private List<AgnisDAL.ServiceAgnis.Module> AssembleModuleInstances(MappingDataSet.ModulesListRow moduleRow)
        {

            List<AgnisDAL.ServiceAgnis.Module> moduleIntances = new List<AgnisDAL.ServiceAgnis.Module>();
            int repeatSeqNumber = 0;
            TranslationAnswer posAnswer = new TranslationAnswer();
            posAnswer.hasAResponse = true;
            //***********************************Normalized repeating modules.***************************************************
            if (moduleRow.Normalized == "Yes")
            {
                //We get the list of permissible values for the Mapping CDE of this module.
                DataView dvModuleMappingQuestionValuesList = MappingInfoDAL.GetValuesListForThisMappingQuestion(dsMappingInfo, moduleRow);

                if (dvModuleMappingQuestionValuesList != null)
                {
                    repeatSeqNumber = 0;
                    //Then we iterate between these permissible values.
                    foreach (DataRowView mappingQuestionValueRowView in dvModuleMappingQuestionValuesList)
                    {
                        //We create the module instance that we are going to add to the modules instances list.
                        //This module instance is going to be added to that list only if 
                        //the question belonging to this module is answered.
                        repeatSeqNumber += 1;
                        textReport = textReport + "Repeat sequence number: " + repeatSeqNumber + "\r\n";
                        AgnisDAL.ServiceAgnis.Module norModule = new AgnisDAL.ServiceAgnis.Module();
                        norModule.publicId = moduleRow.Module_Public_ID;
                        norModule.version = (decimal)moduleRow.Module_Version;
                        norModule.repeatSequenceNumber = repeatSeqNumber.ToString();
                        norModule.publicIdSpecified = true;
                        norModule.versionSpecified = true;
                        MappingDataSet.NormalizedValuesListRow mappingQValue = (MappingDataSet.NormalizedValuesListRow)mappingQuestionValueRowView.Row;
                        List<AgnisDAL.ServiceAgnis.Question> mQuestions = new List<AgnisDAL.ServiceAgnis.Question>();



                        //We fill this module instance with the principal (or mapping) question.
                        AgnisDAL.ServiceAgnis.Question aQuestion = new AgnisDAL.ServiceAgnis.Question();
                        aQuestion.dataElementPublicId = mappingQValue.CDE_Public_ID;
                        aQuestion.dataElementVersion = (decimal)mappingQValue.CDE_Version;
                        aQuestion.value = mappingQValue.Valid_Value_Long_Name;
                        aQuestion.dataElementPublicIdSpecified = true;
                        aQuestion.dataElementVersionSpecified = true;
                        mQuestions.Add(aQuestion);
                        textReport = textReport + "*********************************************************" + "\r\n";
                        textReport = textReport + "Mapping Question: " + mappingQValue.CDE_Public_ID + "\r\n";
                        textReport = textReport + "Mapping Question Value Meaning Text: " + mappingQValue.Value_Meaning_Text + "\r\n";

                        DataView dvModuleQuestionsList = MappingInfoDAL.GetQuestionsListForThisNormalizedModule(dsMappingInfo, mappingQValue);
                        if (dvModuleQuestionsList != null)
                        {
                            foreach (DataRowView questionRowView in dvModuleQuestionsList)
                            {
                                if (moduleRow.Module_Public_ID == 3044975)
                                {

                                }
                                MappingDataSet.MappingQValueQuestionsListRow qValueQuestionRow = (MappingDataSet.MappingQValueQuestionsListRow)questionRowView.Row;
                                DataView dv_ValuesList = MappingInfoDAL.GetPermissibleValuesForThisNormalizedQuestion(dsMappingInfo, qValueQuestionRow, moduleRow);
                                if (dv_ValuesList != null)
                                {
                                    foreach (DataRowView rv_Value in dv_ValuesList)
                                    {


                                        MappingDataSet.NormalizedValuesListRow norValueRow = (MappingDataSet.NormalizedValuesListRow)rv_Value.Row;
                                        TranslationAnswer myAnswer = GetAnswerForThisNormalizedQuestionValueCombination(qValueQuestionRow, norValueRow);
                                        textReport = textReport + "********Sub Question: " + norValueRow.CDE_Public_ID + "\r\n";
                                        textReport = textReport + "Value Meaning Public ID: " + norValueRow["Value Meaning Public ID"].ToString() + "\r\n";
                                        textReport = textReport + "Value Meaning Text: " + norValueRow["Value Meaning Text"].ToString() + "\r\n";
                                        textReport = textReport + "Valid Value Long Name: " + norValueRow["Valid Value Long Name"].ToString() + "\r\n";
                                        textReport = textReport + "Has a Response: " + myAnswer.hasAResponse + "\r\n";



                                        if (myAnswer.hasAResponse == posAnswer.hasAResponse)
                                        {
                                            //If this value was satisfied we fill the question.
                                            AgnisDAL.ServiceAgnis.Question aQuestion2 = new AgnisDAL.ServiceAgnis.Question();
                                            aQuestion2.dataElementPublicId = norValueRow.CDE_Public_ID;
                                            aQuestion2.dataElementVersion = (decimal)norValueRow.CDE_Version;
                                            if (myAnswer.freeTextEntry)
                                            {
                                                aQuestion2.value = myAnswer.textAnswer;
                                            }
                                            else
                                            {
                                                aQuestion2.value = norValueRow.Valid_Value_Long_Name;
                                            }
                                            aQuestion2.dataElementPublicIdSpecified = true;
                                            aQuestion2.dataElementVersionSpecified = true;
                                            mQuestions.Add(aQuestion2);
                                            textReport = textReport + "Response value: " + aQuestion2.value + "\r\n";
                                        }
                                    }
                                }
                            }
                        }
                        if (mQuestions.Count > 1)
                        {
                            norModule.questionCollection = mQuestions.ToArray<AgnisDAL.ServiceAgnis.Question>();
                            moduleIntances.Add(norModule);
                        }
                        else
                        {
                            //repeatSeqNumber -= 1;
                        }
                    }
                }
            }
            //***********************************Non-normalized modules***************************************
            else
            {
                //Non-normalized non-repeating modules
                if (moduleRow.Module_Max_Repeat == 0)
                {
                    //We create the UNIQUE module instance that we are going to add to the modules list just if the question
                    //belonging to this module is answered.
                    repeatSeqNumber = 1;
                    textReport = textReport + "Repeat sequence number: " + repeatSeqNumber + "\r\n";
                    AgnisDAL.ServiceAgnis.Module nonNorModule = new AgnisDAL.ServiceAgnis.Module();
                    nonNorModule.publicId = moduleRow.Module_Public_ID;
                    nonNorModule.version = (decimal)moduleRow.Module_Version;
                    nonNorModule.repeatSequenceNumber = repeatSeqNumber.ToString();
                    nonNorModule.publicIdSpecified = true;
                    nonNorModule.versionSpecified = true;

                    DataView dv_nonNormalizeQuestionsList = MappingInfoDAL.GetQuestionsListForThisModule(dsMappingInfo, moduleRow);
                    List<AgnisDAL.ServiceAgnis.Question> mQuestions = new List<AgnisDAL.ServiceAgnis.Question>();

                    if (dv_nonNormalizeQuestionsList.Count > 0)
                    {
                        //foreach row in my list
                        foreach (DataRowView dv_nonNormalizeQuestionRow in dv_nonNormalizeQuestionsList)
                        {
                            DataRow nonNQestionRow = dv_nonNormalizeQuestionRow.Row;
                            DataView dv_ValuesList = MappingInfoDAL.GetPermissibleValuesForThisNonNormalizedQuestion(dsMappingInfo, nonNQestionRow, moduleRow);

                            textReport = textReport + "*********************************************************" + "\r\n";
                            textReport = textReport + "Question: " + nonNQestionRow["CDE Public ID"].ToString() + "\r\n";
                            textReport = textReport + "Question Long Name: " + nonNQestionRow["Question Long Name"].ToString() + "\r\n";

                            foreach (DataRowView rv_Value in dv_ValuesList)
                            {
                                DataRow nonNorValueRow = (MappingDataSet.NonNormalizedValuesListRow)rv_Value.Row;
                                if (nonNorValueRow["Value Meaning Public ID"].ToString() == "2567168")
                                {

                                }


                                TranslationAnswer myAnswer;
                                myAnswer = GetAnswerForThisNonNormalizedQuestionValueCombination(nonNQestionRow, nonNorValueRow, moduleRow.Module_Max_Repeat);

                                textReport = textReport + "Value Meaning Public ID: " + nonNorValueRow["Value Meaning Public ID"].ToString() + "\r\n";
                                textReport = textReport + "Value Meaning Text: " + nonNorValueRow["Value Meaning Text"].ToString() + "\r\n";
                                textReport = textReport + "Valid Value Long Name: " + nonNorValueRow["Valid Value Long Name"].ToString() + "\r\n";
                                textReport = textReport + "Has a Response: " + myAnswer.hasAResponse + "\r\n";

                                if (myAnswer.hasAResponse == posAnswer.hasAResponse)
                                {
                                    //If this value was satisfied we fill the question.
                                    AgnisDAL.ServiceAgnis.Question aQuestion = new AgnisDAL.ServiceAgnis.Question();
                                    aQuestion.dataElementPublicId = long.Parse(nonNorValueRow["CDE Public ID"].ToString());
                                    aQuestion.dataElementVersion = decimal.Parse(nonNorValueRow["CDE Version"].ToString());
                                    if (myAnswer.freeTextEntry)
                                    {
                                        aQuestion.value = myAnswer.textAnswer;
                                    }
                                    else
                                    {
                                        aQuestion.value = (String)nonNorValueRow["Valid Value Long Name"];
                                    }
                                    aQuestion.dataElementPublicIdSpecified = true;
                                    aQuestion.dataElementVersionSpecified = true;
                                    mQuestions.Add(aQuestion);
                                    textReport = textReport + "Response value: " + aQuestion.value + "\r\n";
                                    break;
                                }
                            }

                        }
                    }
                    if (mQuestions.Count > 0)
                    {
                        nonNorModule.questionCollection = mQuestions.ToArray<AgnisDAL.ServiceAgnis.Question>();
                        moduleIntances.Add(nonNorModule);
                    }
                }

                //Non-normalized repeating modules
                else if (moduleRow.Module_Max_Repeat > 0)
                {
                    if (moduleRow.Module_Public_ID == 3043802)  //1st
                    {

                    }

                    List<AgnisDAL.ServiceAgnis.Question> valueMeaningIDsAnswers = new List<AgnisDAL.ServiceAgnis.Question>();
                    List<BackupValueAnswer> valueAnswers = new List<BackupValueAnswer>();
                    for (int i = 1; i <= moduleRow.Module_Max_Repeat + 1; i++)
                    {
                        repeatSeqNumber = i;
                        textReport = textReport + "Repeat sequence number: " + repeatSeqNumber + "\r\n";
                        AgnisDAL.ServiceAgnis.Module nonNorModule = new AgnisDAL.ServiceAgnis.Module();
                        nonNorModule.publicId = moduleRow.Module_Public_ID;
                        nonNorModule.version = (decimal)moduleRow.Module_Version;
                        nonNorModule.repeatSequenceNumber = repeatSeqNumber.ToString();
                        nonNorModule.publicIdSpecified = true;
                        nonNorModule.versionSpecified = true;

                        DataView dv_nonNormalizeQuestionsList = MappingInfoDAL.GetQuestionsListForThisModule(dsMappingInfo, moduleRow);
                        List<AgnisDAL.ServiceAgnis.Question> mQuestions = new List<AgnisDAL.ServiceAgnis.Question>();
                        if (dv_nonNormalizeQuestionsList.Count > 0)
                        {
                            foreach (DataRowView dv_nonNormalizeQuestionRow in dv_nonNormalizeQuestionsList)
                            {
                                DataRow nonNQestionRow = dv_nonNormalizeQuestionRow.Row;
                                DataView dv_ValuesList = MappingInfoDAL.GetPermissibleValuesForThisNonNormalizedQuestion(dsMappingInfo, nonNQestionRow, moduleRow);
                                textReport = textReport + "*********************************************************" + "\r\n";
                                textReport = textReport + "Question: " + nonNQestionRow["CDE Public ID"].ToString() + "\r\n";
                                textReport = textReport + "Question Long Name: " + nonNQestionRow["Question Long Name"].ToString() + "\r\n";

                                if (nonNQestionRow["CDE Public ID"].ToString() == "2681520")
                                {

                                }

                                if (dv_ValuesList != null)
                                {
                                    foreach (DataRowView rv_Value in dv_ValuesList)
                                    {
                                        DataRow nonNorValueRow = rv_Value.Row;
                                        TranslationAnswer myAnswer = null;
                                        bool valueAlreadyTested = false;
                                        //************** Section to verify if we have already tested a value**********************
                                        foreach (BackupValueAnswer tAnswer in valueAnswers)
                                        {
                                            if (tAnswer.value == nonNorValueRow["Valid Value Long Name"].ToString())
                                            {
                                                //If the value alread exist into the backup list of tested values
                                                //We copy the answer.
                                                myAnswer = new TranslationAnswer();
                                                myAnswer.hasAResponse = tAnswer.hasResponse;
                                                myAnswer.freeTextEntry = tAnswer.freeTextEntry;
                                                valueAlreadyTested = true;
                                                break;
                                            }
                                        }
                                        if (!valueAlreadyTested)
                                        {
                                            //If the value was not already tested we start the test as normally.
                                            myAnswer = GetAnswerForThisNonNormalizedQuestionValueCombination(nonNQestionRow, nonNorValueRow, i);
                                            //We add the new answer to the backup list of tested values.
                                            valueAnswers.Add(new BackupValueAnswer(nonNorValueRow["Valid Value Long Name"].ToString(), myAnswer.hasAResponse, myAnswer.freeTextEntry));
                                        }
                                        //****************************************************************************************
                                        textReport = textReport + "Value Meaning Public ID: " + nonNorValueRow["Value Meaning Public ID"].ToString() + "\r\n";
                                        textReport = textReport + "Value Meaning Text: " + nonNorValueRow["Value Meaning Text"].ToString() + "\r\n";
                                        textReport = textReport + "Valid Value Long Name: " + nonNorValueRow["Valid Value Long Name"].ToString() + "\r\n";
                                        textReport = textReport + "Has a Response: " + myAnswer.hasAResponse + "\r\n";

                                        if (myAnswer.hasAResponse == true)
                                        {
                                            //If this value was satisfied we fill the question.
                                            AgnisDAL.ServiceAgnis.Question aQuestion = new AgnisDAL.ServiceAgnis.Question();
                                            aQuestion.dataElementPublicId = long.Parse(nonNorValueRow["CDE Public ID"].ToString());
                                            aQuestion.dataElementVersion = decimal.Parse(nonNorValueRow["CDE Version"].ToString());
                                            if (myAnswer.freeTextEntry)
                                            {
                                                aQuestion.value = myAnswer.textAnswer;
                                                aQuestion.dataElementPublicIdSpecified = true;
                                                aQuestion.dataElementVersionSpecified = true;
                                                mQuestions.Add(aQuestion);
                                                break;
                                            }
                                            else
                                            {
                                                aQuestion.value = (String)nonNorValueRow["Valid Value Long Name"];
                                                bool valueAlreadyExist = false;
                                                foreach (AgnisDAL.ServiceAgnis.Question tAnswer in valueMeaningIDsAnswers)
                                                {
                                                    if (tAnswer.value == aQuestion.value)
                                                    {
                                                        valueAlreadyExist = true;
                                                        break;
                                                    }
                                                }

                                                if (!valueAlreadyExist)
                                                {
                                                    aQuestion.dataElementPublicIdSpecified = true;
                                                    aQuestion.dataElementVersionSpecified = true;
                                                    mQuestions.Add(aQuestion);
                                                    valueMeaningIDsAnswers.Add(aQuestion);
                                                    break;
                                                }
                                            }
                                            textReport = textReport + "Response value: " + aQuestion.value + "\r\n";
                                        }
                                    }
                                }
                            }
                        }
                        //if (mQuestions.Count == dv_nonNormalizeQuestionsList.Count)
                        if (mQuestions.Count > 1)
                        {
                            nonNorModule.questionCollection = mQuestions.ToArray<AgnisDAL.ServiceAgnis.Question>();
                            moduleIntances.Add(nonNorModule);
                        }

                    }
                }
            }
            //***************************************************************************************************
            return moduleIntances;
        }

        /// <summary>
        /// RRA update for submition
        /// </summary>
        private List<AgnisDAL.ServiceAgnis.Module> UpdateModuleInstances(string instance_id)
        {
            List<AgnisDAL.ServiceAgnis.Module> moduleIntances = new List<AgnisDAL.ServiceAgnis.Module>();

            //specific Module for an update submitting
            int repeatSeqNumber = 1;
            AgnisDAL.ServiceAgnis.Module nonNorModule = new AgnisDAL.ServiceAgnis.Module();
            nonNorModule.publicId = 2892372;
            nonNorModule.version = 1;
            nonNorModule.repeatSequenceNumber = repeatSeqNumber.ToString();
            nonNorModule.publicIdSpecified = true;
            nonNorModule.versionSpecified = true;

            //DataView dv_nonNormalizeQuestionsList = MappingInfoDAL.GetQuestionsListForThisModule(dsMappingInfo, moduleRow);
            List<AgnisDAL.ServiceAgnis.Question> mQuestions = new List<AgnisDAL.ServiceAgnis.Question>();

            AgnisDAL.ServiceAgnis.Question aQuestion = new AgnisDAL.ServiceAgnis.Question();
            aQuestion.dataElementPublicId = long.Parse("2527889");
            aQuestion.dataElementVersion = decimal.Parse("1");
            aQuestion.value = instance_id;
            aQuestion.dataElementPublicIdSpecified = true;
            aQuestion.dataElementVersionSpecified = true;
            mQuestions.Add(aQuestion);

            if (mQuestions.Count > 0)
            {
                nonNorModule.questionCollection = mQuestions.ToArray<AgnisDAL.ServiceAgnis.Question>();
                moduleIntances.Add(nonNorModule);
            }

            return moduleIntances;
        }
        private class BackupValueAnswer
        {
            public String value;
            public bool hasResponse;
            public bool freeTextEntry;

            public BackupValueAnswer(String val, bool resp, bool isTextEntry)
            {
                value = val;
                hasResponse = resp;
                freeTextEntry = isTextEntry;
            }
        }
        #endregion

        #region Translation logic

        /// <summary>
        /// Gets the datarow for this normalized question-value combination.
        /// </summary>
        /// <param name="qValueQuestion"></param>
        /// <param name="valueRow"></param>
        /// <returns>A FieldValuesRow object.</returns>
        public MappingDataSet.FieldValuesRow GetRowForThisNormalizedQuestionValueCombination(MappingDataSet.MappingQValueQuestionsListRow qValueQuestion, MappingDataSet.NormalizedValuesListRow valueRow)
        {
            DataView myVariableView = new DataView(dsMappingInfo.FieldValues);
            if (valueRow["Value Meaning Public ID"] != System.DBNull.Value)
            {
                myVariableView.RowFilter = "[Module Public ID]='" + qValueQuestion.Module_Public_ID + "' AND "
                                                                    + "[Module Version]='" + qValueQuestion.Module_Version + "' AND "
                                                                    + "[Value Meaning Public ID]='" + qValueQuestion.Value_Meaning_Public_ID + "' AND "
                                                                    + "[Value Meaning Version]='" + qValueQuestion.Value_Meaning_Version + "' AND "
                                                                    + "[CDE Public ID 2]='" + valueRow.CDE_Public_ID + "' AND "
                                                                    + "[CDE Version 2]='" + valueRow.CDE_Version + "' AND "
                                                                    + "[Value Meaning Public ID 2]='" + valueRow.Value_Meaning_Public_ID + "' AND "
                                                                    + "[Value Meaning Version 2]='" + valueRow.Value_Meaning_Version + "'";
            }
            else
            {
                myVariableView.RowFilter = "[Module Public ID]='" + qValueQuestion.Module_Public_ID + "' AND "
                                                                    + "[Module Version]='" + qValueQuestion.Module_Version + "' AND "
                                                                    + "[Value Meaning Public ID]='" + qValueQuestion.Value_Meaning_Public_ID + "' AND "
                                                                    + "[Value Meaning Version]='" + qValueQuestion.Value_Meaning_Version + "' AND "
                                                                    + "[CDE Public ID 2]='" + valueRow.CDE_Public_ID + "' AND "
                                                                    + "[CDE Version 2]='" + valueRow.CDE_Version + "'";
            }
            if (myVariableView.Count > 0)
            {
                MappingDataSet.FieldValuesRow varRow = (MappingDataSet.FieldValuesRow)myVariableView[0].Row;
                return varRow;
            }
            else
            {
                throw new TranslationException("The program didn't find any rows while filtering the Variables table.");
            }
        }

        /// <summary>
        /// Gets the datarow for this non-normalized question-value combination.
        /// </summary>
        /// <param name="questionValueRow"></param>
        /// <param name="valueRow"></param>
        /// <returns>A FieldValuesRow object.</returns>
        public MappingDataSet.FieldValuesRow GetRowForThisNonNormalizedQuestionValueCombination(DataRow questionValueRow, DataRow valueRow)
        {
            DataView myVariableView = new DataView(dsMappingInfo.FieldValues);
            if (valueRow["Value Meaning Public ID"] != System.DBNull.Value)
            {
                myVariableView.RowFilter = "[Module Public ID]='" + questionValueRow["Module Public ID"] + "' AND "
                                                    + "[Module Version]='" + questionValueRow["Module Version"] + "' AND "
                                                    + "[CDE Public ID]='" + questionValueRow["CDE Public ID"] + "' AND "
                                                    + "[CDE Version]='" + questionValueRow["CDE Version"] + "' AND "
                                                    + "[Value Meaning Public ID]='" + valueRow["Value Meaning Public ID"] + "' AND "
                                                    + "[Value Meaning Version]='" + valueRow["Value Meaning Version"] + "'";
            }
            else
            {
                myVariableView.RowFilter = "[Module Public ID]='" + questionValueRow["Module Public ID"] + "' AND "
                                                    + "[Module Version]='" + questionValueRow["Module Version"] + "' AND "
                                                    + "[CDE Public ID]='" + questionValueRow["CDE Public ID"] + "' AND "
                                                    + "[CDE Version]='" + questionValueRow["CDE Version"] + "'";
            }
            if (myVariableView.Count == 1)
            {
                MappingDataSet.FieldValuesRow varRow = (MappingDataSet.FieldValuesRow)myVariableView[0].Row;
                return varRow;
            }
            else
            {
                throw new TranslationException("The program didn't find a unique row or any rows while filtering the Variables table.");
            }
        }

        /// <summary>
        /// Does the record selection process.
        /// </summary>
        /// <param name="varRow"></param>
        /// <param name="isPreSelection"></param>
        /// <param name="repeatingSequenceNumber"></param>
        /// <returns>Returns a filtered dataset after applying all the record selection filters.</returns>
        public DataSet DoRecordsSelection(MappingDataSet.FieldValuesRow varRow, bool isPreSelection, int repeatingSequenceNumber)
        {
            String recordsSelectionGroupID;
            if (varRow.HasSelection == "Yes" || (varRow.HasPreSelection == "Yes" && isPreSelection))
            {
                if (isPreSelection)
                {
                    recordsSelectionGroupID = varRow.EBMT_PreSelection_ID;
                }
                else
                {
                    try
                    {
                        recordsSelectionGroupID = varRow.EBMT_Records_Selection_ID; ;
                    }
                    catch
                    {
                        throw new Exception();
                    }
                }
                if (recordsSelectionGroupID == "GS2450-2-076")
                {

                }
                //*********************We apply the records selection.************************************
                //We instantiate a temporary empty dataset to fill with the resulting rows of our record selection process.
                DataSet dsTemp = new DataSet();
                BindingSource bsRecordsSelectionGroups = new BindingSource();
                bsRecordsSelectionGroups.DataSource = dsMappingInfo;
                bsRecordsSelectionGroups.DataMember = dsMappingInfo.RecordsSelectionGroups.TableName;
                bsRecordsSelectionGroups.Filter = "[EBMT Selections Group ID]='" + recordsSelectionGroupID + "'";

                if (bsRecordsSelectionGroups.Count > 0)
                {
                    //For each record selection item in the record selection group
                    //we apply the filters and return the datarows.
                    foreach (DataRowView drView in bsRecordsSelectionGroups.List)
                    {
                        MappingDataSet.RecordsSelectionGroupsRow drRecordsSelectionGroup = (MappingDataSet.RecordsSelectionGroupsRow)drView.Row;
                        dsTemp.Merge(EbmtDAL.EbmtDAL.ApplyRecordsSelectionG2(dsMappingInfo, drRecordsSelectionGroup.EBMT_Selections_ID, repeatingSequenceNumber, dateOfTransplant));
                    }
                }
                return dsTemp;
            }
            else
            {
                //*******************We return an unfiltered EBMT dataset object.***************************
                return EbmtDAL.EbmtDAL.GetNonFilteredEBMTDataSetG2();
            }
        }

        /// <summary>
        /// Does the pre-conditions process if there is any.
        /// </summary>
        /// <param name="varRow"></param>
        /// <param name="valueRow"></param>
        /// <param name="repeatingSequenceNumber"></param>
        /// <returns>True if the precondition process was tested succesfull, false if not.</returns>
        public Boolean DoPreConditions(MappingDataSet.FieldValuesRow varRow, DataRow valueRow, int repeatingSequenceNumber)
        {
            if (varRow["HasPreConditions"] != System.DBNull.Value)
            {
                if (varRow.HasPreConditions == "Yes")
                {
                    //We apply the records pre-selection for this mapping definition.
                    dsFilteredEbmtPatientG = DoRecordsSelection(varRow, true, repeatingSequenceNumber);

                    //We use a TranslationAnswer object to retrieve the PreCondition test result.
                    TranslationAnswer preAnswer = new TranslationAnswer();
                    preAnswer = DoMappingConditions(varRow, true, valueRow); ;

                    if (preAnswer.hasAResponse == true)
                    { return true; }
                    else { return false; }
                }
                else
                {
                    return true;
                }
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// Does the MappingConditions process.
        /// Process each ConditionId from the list of conditions in the group.
        /// </summary>
        /// <param name="varRow"></param>
        /// <param name="isPreCondition"></param>
        /// <param name="valueRow"></param>
        /// <returns>A TranslationAnswer object containing the result of testing the conditions process.</returns>
        public TranslationAnswer DoMappingConditions(MappingDataSet.FieldValuesRow varRow, bool isPreCondition, DataRow valueRow)
        {
            TranslationAnswer myAnswer = new TranslationAnswer();
            BindingSource bsMappingConditionsGroups = new BindingSource();
            bsMappingConditionsGroups.DataSource = dsMappingInfo;
            bsMappingConditionsGroups.DataMember = "MappingConditionsGroups";
            String mappingConditionGroupID;
            if (isPreCondition)
            {
                mappingConditionGroupID = varRow.EBMT_PreConditions_ID;
                textReport2 = textReport2 + "Pre Conditions Group Id:" + varRow.EBMT_PreConditions_ID + "\r\n";
            }
            else
            {
                mappingConditionGroupID = varRow.EBMT_Conditions_ID;
                textReport2 = textReport2 + "Conditions Group Id:" + varRow.EBMT_Conditions_ID + "\r\n";
            }
            bsMappingConditionsGroups.Filter = "[EBMT Conditions Group ID]='" + mappingConditionGroupID + "'";

            if(mappingConditionGroupID == "GC2400-1-041")
            {

            }

            if (bsMappingConditionsGroups.Count > 0)
            {
                bool RelationResultAnd = true;
                bool RelationResultOr = false;

                foreach (DataRowView drView in bsMappingConditionsGroups.List)
                {
                    TranslationAnswer tempAnswer = new TranslationAnswer();

                    MappingDataSet.MappingConditionsGroupsRow drConditions = (MappingDataSet.MappingConditionsGroupsRow)drView.Row;
                    if (drConditions["RelationshipOperator"] != System.DBNull.Value)
                    {
                        if (drConditions.RelationshipOperator == "OR")
                        {
                            RelationResultAnd = false;
                            tempAnswer = ProcessConditionId(drConditions, varRow, valueRow);
                            RelationResultOr = RelationResultOr || tempAnswer.hasAResponse;
                            if (tempAnswer.hasAResponse)
                            {
                                myAnswer = tempAnswer;
                            }
                        }
                        else
                        {
                            tempAnswer = ProcessConditionId(drConditions, varRow, valueRow);
                            RelationResultAnd = RelationResultAnd && tempAnswer.hasAResponse;
                            myAnswer = tempAnswer;
                        }
                    }
                    else
                    {
                        tempAnswer = ProcessConditionId(drConditions, varRow, valueRow);
                        RelationResultAnd = RelationResultAnd && tempAnswer.hasAResponse;
                        myAnswer = tempAnswer;
                    }
                }
                if (RelationResultAnd || RelationResultOr)
                {
                    return myAnswer;
                }
                else
                {
                    myAnswer.hasAResponse = false;
                    return myAnswer;
                }
            }
            else
            {
                throw new TranslationException("There is no condition using this ID.");
            }
        }

        /// <summary>
        /// Process this Condition Id using the Conditions instructions.
        /// Depending on the Instruction this method calls the GetResultOfTestingConditionIdExpressions method: 
        /// When "All must be true" is specified: it calls this method for each datarow on the filtered dataset 
        /// unless it finds a false value.
        /// When "Stop at last true value" is specified, it calls this method for each datarow on the filtered dataset 
        /// and returns the last true value if there was any.
        /// When any other instruction or when there is not instruction:
        /// it calls the same method for each datarow until finding a true value.
        /// </summary>
        /// <param name="drConditions"></param>
        /// <param name="varRow"></param>
        /// <param name="valueRow"></param>
        /// <returns>A TranslationAnswer object containing the result of the test.</returns>
        public TranslationAnswer ProcessConditionId(MappingDataSet.MappingConditionsGroupsRow drConditions, MappingDataSet.FieldValuesRow varRow, DataRow valueRow)
        {
            textReport2 = textReport2 + "Processing Condition ID:" + drConditions.EBMT_Conditions_ID + "\r\n";
            TranslationAnswer myAnswer = new TranslationAnswer(drConditions.EBMT_Conditions_ID);
            if (drConditions["Conditions Instruction"] != System.DBNull.Value)
            {
                //Conditions Instructions are only specified for RecordSelections returning multiple rows.
                //When recordsSelection return multiple rows it can be from only one table.
                if (drConditions.Conditions_Instruction == "All must be true")
                {
                    if (dsFilteredEbmtPatientG.Tables.Contains(drConditions.EBMT_ConTable_ID))
                    {
                        myAnswer.hasAResponse = true;
                        foreach (DataRow dRow in dsFilteredEbmtPatientG.Tables[drConditions.EBMT_ConTable_ID].Rows)
                        {
                            DataSet ebmtResultDataSet = new DataSet();
                            DataRow[] dRows = new DataRow[1];
                            dRows[0] = dRow;
                            ebmtResultDataSet.Merge(dRows);
                            TranslationAnswer tempAnswer = new TranslationAnswer(drConditions.EBMT_Conditions_ID);
                            tempAnswer = GetResultOfTestingConditionIdExpressions(drConditions.EBMT_Conditions_ID, valueRow, varRow, ebmtResultDataSet);
                            tempAnswer.ConditionId = drConditions.EBMT_Conditions_ID;
                            myAnswer.hasAResponse = myAnswer.hasAResponse && tempAnswer.hasAResponse;
                            myAnswer.freeTextEntry = tempAnswer.freeTextEntry;
                            myAnswer.textAnswer = tempAnswer.textAnswer;
                            myAnswer.valueMeaningPublicId = tempAnswer.valueMeaningPublicId;
                        }
                        //if (myAnswer.hasAResponse)
                        //{
                        //    //myAnswer.normalized = true;  RRA le 28/07                                
                        //    myAnswer.textAnswer = tempAnswer.textAnswer;
                        //    myAnswer.valueMeaningPublicId = tempAnswer.valueMeaningPublicId;
                        //}
                        //else
                        //{
                        //    //myAnswer.normalized = false; RRA le 28/07
                        //    return myAnswer;
                        //}
                    }
                    textReport2 = textReport2 + "   Answer:" + myAnswer.hasAResponse + "\r\n";
                    return myAnswer;
                }
                else if (drConditions.Conditions_Instruction == "Stop at last true value")
                {
                    if (dsFilteredEbmtPatientG.Tables.Contains(drConditions.EBMT_ConTable_ID))
                    {
                        foreach (DataRow dRow in dsFilteredEbmtPatientG.Tables[drConditions.EBMT_ConTable_ID].Rows)
                        {
                            DataSet ebmtResultDataSet = new DataSet();
                            DataRow[] dRows = new DataRow[1];
                            dRows[0] = dRow;
                            ebmtResultDataSet.Merge(dRows);
                            TranslationAnswer tempAnswer = new TranslationAnswer(drConditions.EBMT_Conditions_ID);
                            tempAnswer = GetResultOfTestingConditionIdExpressions(drConditions.EBMT_Conditions_ID, valueRow, varRow, ebmtResultDataSet);
                            tempAnswer.ConditionId = drConditions.EBMT_Conditions_ID;
                            if (tempAnswer.hasAResponse)
                            {
                                myAnswer.hasAResponse = tempAnswer.hasAResponse;
                                //myAnswer.normalized = true;  RRA le 28/07
                                myAnswer.textAnswer = tempAnswer.textAnswer;
                                myAnswer.valueMeaningPublicId = tempAnswer.valueMeaningPublicId;
                            }
                        }
                    }
                    textReport2 = textReport2 + "   Answer:" + myAnswer.hasAResponse + "\r\n";
                    return myAnswer;
                }
                else
                {
                    //"Stop at first true value"
                    if (dsFilteredEbmtPatientG.Tables.Contains(drConditions.EBMT_ConTable_ID))
                    {

                        foreach (DataRow dRow in dsFilteredEbmtPatientG.Tables[drConditions.EBMT_ConTable_ID].Rows)
                        {
                            DataSet ebmtResultDataSet = new DataSet();
                            DataRow[] dRows = new DataRow[1];
                            dRows[0] = dRow;
                            ebmtResultDataSet.Merge(dRows);
                            TranslationAnswer tempAnswer = new TranslationAnswer(drConditions.EBMT_Conditions_ID);
                            tempAnswer = GetResultOfTestingConditionIdExpressions(drConditions.EBMT_Conditions_ID, valueRow, varRow, ebmtResultDataSet);
                            tempAnswer.ConditionId = drConditions.EBMT_Conditions_ID;
                            if (tempAnswer.hasAResponse)
                            {
                                return tempAnswer;
                            }
                        }
                    }
                    textReport2 = textReport2 + "   Answer:" + myAnswer.hasAResponse + "\r\n";
                    return myAnswer;
                }
            }
            else
            {
                if (varRow.HasSelection == "Yes")
                {
                    //We make sure that the table(s) in the dataset contains only one row.
                    //If not we throw an Exception.
                    if (dsFilteredEbmtPatientG.Tables.Count > 1)
                    {
                        foreach (DataTable t in dsFilteredEbmtPatientG.Tables)
                        {
                            if (t.Rows.Count != 1)
                            {
                                throw new TranslationException("Multiples rows have been selected and no Conditions Instruction was given.");
                            }
                        }
                    }
                }
                myAnswer = GetResultOfTestingConditionIdExpressions(drConditions.EBMT_Conditions_ID, valueRow, varRow, dsFilteredEbmtPatientG);
                myAnswer.ConditionId = drConditions.EBMT_Conditions_ID;
                textReport2 = textReport2 + "   Answer:" + myAnswer.hasAResponse + "\r\n";
                return myAnswer;
            }
        }

        public TranslationAnswer GetAnswerForThisQuestionValueCombination(MappingDataSet.FieldValuesRow varRow,
                                                           DataRow valueRow, int repeatingSequenceNumber)
        {
            // We prepare the TranslationAnswer object that we are going to send.
            TranslationAnswer myAnswer = new TranslationAnswer();
            //We process this answer only if there is a correspondence into the EBMT database.
            if (varRow.Correspondence_in_EBMT == "Yes")
            {
                //Reset all filters binded to our EBMT original dataset.
                EbmtDAL.EbmtDAL.ResetBindingSourcesRowFiltersG();
                //If the temporary EBMT filtered dataset already exist, we clear any data.
                if (dsFilteredEbmtPatientG != null) dsFilteredEbmtPatientG.Clear();
                //*****If there is a preConditions step we process the PreConditions.***************************
                if (DoPreConditions(varRow, valueRow, repeatingSequenceNumber) == false)
                {
                    //If the preCondition test was negative
                    //we stops the process and return the empty TranslationAnswer object.
                    textReport2 = textReport2 + "Preconditions return false." + "\r\n";
                    //myAnswer is False then we return myAnswer.
                    return myAnswer;
                }
                //If the preCondition test is positive we let the program to continue processing
                //this Field-Value combination.
                //Reset all filters binded to our EBMT original dataset.
                EbmtDAL.EbmtDAL.ResetBindingSourcesRowFiltersG();
                //If the temporary EBMT filtered dataset already exist, we clear any data.
                if (dsFilteredEbmtPatientG != null) dsFilteredEbmtPatientG.Clear();
                //*****Do the Records Selection process.*******************************************************
                dsFilteredEbmtPatientG = DoRecordsSelection(varRow, false, repeatingSequenceNumber);
                //*****Truly named Mapping process***************************************************************
                if (varRow.HasConditions == "Yes")
                {
                    TranslationAnswer tempAnswer = DoMappingConditions(varRow, false, valueRow);
                    //Erased with D.Pacheco in order to fix the problem concerning the DOSEs for the drugs.
                    //if (varRow["CopyEBMTValue"] != System.DBNull.Value)
                    //{
                    //    if (varRow.CopyEBMTValue == "Yes")
                    //    {
                    //        if (tempAnswer.hasAResponse)
                    //        { return CopyEbmtValue(varRow, dsFilteredEbmtPatientG); }
                    //        else
                    //        { return new TranslationAnswer(); }
                    //    }
                    //    else
                    //    {
                    //        return tempAnswer;
                    //    }
                    //}
                    //else 
                    //{
                    //    return tempAnswer;
                    //}
                    return tempAnswer;
                }
                else
                {
                    if (varRow["CopyEBMTValue"] != System.DBNull.Value)
                    {
                        if (varRow.CopyEBMTValue == "Yes")
                        {
                            //If there is no conditions to accomplish and we need to copy the real string value from the database.
                            //We just need to verify if there is already some text data in order to send if not we do nothing.
                            //If there is a value send true
                            return CopyEbmtValue(varRow, dsFilteredEbmtPatientG);
                        }
                        else
                        {
                            throw new TranslationException("HasConditions is 'No' and CopyEBMTValue is different of 'Yes'."
                                + "\r\nPlease verify: when HasConditions is 'No' or NULL, CopyEBMTValue must be 'Yes'.");
                        }
                    }
                    else
                    {
                        throw new TranslationException("HasConditions is different of 'Yes' and CopyEBMTValue is NULL."
                            + "Please verify: when HasConditions is 'No' or NULL, CopyEBMTValue must be 'Yes'.");
                    }
                }
            }
            else
            {
                myAnswer.hasAResponse = false;
                return myAnswer;
            }
        }
        /// <summary>
        /// If the EBMT database has a value matching exactly this QuestionValue combination, the TranslationAnswer object
        /// will have its property hasAResponse as true.
        /// If the EBMT database hasn't a value matching this QuestionValue combination, the TranslationAnswer object
        /// will have its property hasAResponse as false.
        /// </summary>
        /// <param name="qValueQuestion"></param>
        /// <param name="valueRow"></param>
        /// <returns></returns>
        public TranslationAnswer GetAnswerForThisNormalizedQuestionValueCombination(MappingDataSet.MappingQValueQuestionsListRow qValueQuestion,
                                                           MappingDataSet.NormalizedValuesListRow valueRow)
        {
            // We prepare the TranslationAnswer object that we are going to send.
            TranslationAnswer myAnswer = new TranslationAnswer();
            //We get the row corresponding to this field-value cmbination.
            MappingDataSet.FieldValuesRow varRow = GetRowForThisNormalizedQuestionValueCombination(qValueQuestion, valueRow);
            if (varRow["IsMappingException"] == System.DBNull.Value)
            {
                return GetAnswerForThisQuestionValueCombination(varRow, valueRow, 0);
            }
            else if (varRow.IsMappingException == "Yes" || varRow.IsMappingException == "YES")
            {
                return GetMappingExceptionValue(varRow);
            }
            else
            {
                return GetAnswerForThisQuestionValueCombination(varRow, valueRow, 0);
            }
        }

        public TranslationAnswer GetAnswerForThisNonNormalizedQuestionValueCombination(DataRow questionValueRow,
                                                              DataRow valueRow,
                                                              int repeatingSequenceNumber)
        {
            //We prepare the TranslationAnswer object that we need to send as the value resulting from this function.
            TranslationAnswer myAnswer = new TranslationAnswer();
            //We get the FieldValue row for this question value combination.
            MappingDataSet.FieldValuesRow varRow = GetRowForThisNonNormalizedQuestionValueCombination(questionValueRow, valueRow);
            if (varRow["IsMappingException"] == System.DBNull.Value)
            {
                return GetAnswerForThisQuestionValueCombination(varRow, valueRow, repeatingSequenceNumber);
            }
            else if (varRow["IsMappingException"].ToString() == "Yes" || varRow["IsMappingException"].ToString() == "YES")
            {
                return GetMappingExceptionValue(varRow);
            }
            else
            {
                return GetAnswerForThisQuestionValueCombination(varRow, valueRow, repeatingSequenceNumber);
            }
        }

        public TranslationAnswer GetMappingExceptionValue(MappingDataSet.FieldValuesRow varRow)
        {
            TranslationAnswer myAnswer = new TranslationAnswer();
            EbmtDAL.TranslationAnswer dalAnwser = new EbmtDAL.TranslationAnswer();
            switch (varRow.ExceptionFunctionName.Trim())
            {
                case "Get_other_unit_name_specify":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_other_unit_name_specify();
                    break;
                case "Get_N_MN_LMM_DIS_DIA_IND_Value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_N_MN_LMM_DIS_DIA_IND_Value(dateOfTransplant);
                    break;
                case "Get_NMN_LMM_DIS_DX_DT_Value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_NMN_LMM_DIS_DX_DT_Value(dateOfTransplant);
                    break;
                case "Get_R_O_P_D_O_D_D_C_H_F_Value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_R_O_P_D_O_D_D_C_H_F_Value(dateOfTransplant);
                    break;
                case "Get_R_O_P_D_O_D_D_C_H_D_Value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_R_O_P_D_O_D_D_C_H_D_Value(dateOfTransplant);
                    break;
                case "Get_Today_Date":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_Today_Date();
                    break;
                case "Get_Contact_Firstname":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_Contact_Firstname();
                    break;
                case "Get_Contact_Lastname":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_Contact_Lastname();
                    break;
                case "Get_Contact_PhoneNumber":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_Contact_PhoneNumber();
                    break;
                case "Get_Contact_Fax":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_Contact_Fax();
                    break;
                case "Get_Contact_Email":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_Contact_Email();
                    break;
                case "Get_FollowUp_Type_Period":
                    switch (currentAgnisFormDuePeriod)
                    {
                        case AgnisForm2450DuePeriods.HundredDays:
                            dalAnwser = EbmtDAL.EbmtDAL.Get_FollowUp_Type_Period(varRow.Valid_Value_Long_Name, "Day 100");
                            break;
                        case AgnisForm2450DuePeriods.SixtMonths:
                            dalAnwser = EbmtDAL.EbmtDAL.Get_FollowUp_Type_Period(varRow.Valid_Value_Long_Name, "6 Months");
                            break;
                        default:
                            dalAnwser = EbmtDAL.EbmtDAL.Get_FollowUp_Type_Period(varRow.Valid_Value_Long_Name, "Annual");
                            break;
                    }
                    break;
                //RRA 2900
                case "Get_CTRB_DTH_RSN_TP_A_Value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_CTRB_DTH_RSN_TP_A_Value(dateOfTransplant);
                    break;
                case "Get_CTRB_DTH_RSN_TP_B_Value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_CTRB_DTH_RSN_TP_B_Value(dateOfTransplant);
                    break;
                case "Get_PRM_DTH_RSN_SPEC_Value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_PRM_DTH_RSN_SPEC_Value(dateOfTransplant);
                    break;
                case "Get_DTH_RSN_CNF_AUTP_IND_Value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_DTH_RSN_CNF_AUTP_IND_Value();
                    break;
                //RRA 2400
                case "Get_HSCT_PRIM_DIAG_DT_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_HSCT_PRIM_DIAG_DT_value(dateOfTransplant);
                    break;
                case "Get_HSCT_PRI_DIS_TYP_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_HSCT_PRI_DIS_TYP_value(dateOfTransplant);
                    break;
                case "Get_TX_REL_AML_DX_DX_I_3_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_TX_REL_AML_DX_DX_I_3_value(dateOfTransplant);
                    break;
                case "Get_TX_AML_ETLGY_OCR_IND_A_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_TX_AML_ETLGY_OCR_IND_A_value(dateOfTransplant);
                    break;
                case "Get_TX_AML_ETLGY_OCR_IND_B_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_TX_AML_ETLGY_OCR_IND_B_value(dateOfTransplant);
                    break;
                case "Get_TX_AML_ETLGY_OCR_IND_C_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_TX_AML_ETLGY_OCR_IND_C_value(dateOfTransplant);
                    break;
                case "Get_AML_PR_IMTNB_TX_IND3_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_AML_PR_IMTNB_TX_IND3_value(dateOfTransplant);
                    break;
                case "Get_AML_TRN_ALEUK_STAT_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_AML_TRN_ALEUK_STAT_value(dateOfTransplant);
                    break;
                case "Get_AML_CYT_CR_Y_N_U_IND_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_AML_CYT_CR_Y_N_U_IND_value(dateOfTransplant);
                    break;
                case "Get_AML_MOL_CR_Y_N_U_IND_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_AML_MOL_CR_Y_N_U_IND_value(dateOfTransplant);
                    break;
                case "Get_AML_TRN_CR_DS_ST_CT_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_AML_TRN_CR_DS_ST_CT_value(dateOfTransplant);
                    break;
                case "Get_AML_TRN_RLPS_ST_CT_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_AML_TRN_RLPS_ST_CT_value(dateOfTransplant);
                    break;
                case "Get_TCELL_NHL_CLASS_SP_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_TCELL_NHL_CLASS_SP_value(dateOfTransplant);
                    break;
                case "Get_O_DZ_DX_SPEC_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_O_DZ_DX_SPEC_value(dateOfTransplant);
                    break;
                case "Get_OTHR_CNCR_CLS_DX_SPC_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_OTHR_CNCR_CLS_DX_SPC_value(dateOfTransplant);
                    break;
                case "Get_O_CTYPNA_SNDRM_SPEC_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_O_CTYPNA_SNDRM_SPEC_value(dateOfTransplant);
                    break;
                case "Get_OTHR_GNTC_ANM_CLS_SP_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_OTHR_GNTC_ANM_CLS_SP_value(dateOfTransplant);
                    break;
                case "Get_CNG_MTB_DS_OTR_TP_SP_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_CNG_MTB_DS_OTR_TP_SP_value(dateOfTransplant);
                    break;
                case "Get_IMN_DS_O_SCID_CLS_SP_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_IMN_DS_O_SCID_CLS_SP_value(dateOfTransplant);
                    break;
                case "Get_IMN_DSRDR_O_CLS_SPEC_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_IMN_DSRDR_O_CLS_SPEC_value(dateOfTransplant);
                    break;
                case "Get_O_CNTV_TSE_DS_TP_SPC_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_O_CNTV_TSE_DS_TP_SPC_value(dateOfTransplant);
                    break;
                case "Get_VAS_OTHR_CLS_DX_SPC_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_VAS_OTHR_CLS_DX_SPC_value(dateOfTransplant);
                    break;
                case "Get_ARTH_OTHR_CLS_SPEC_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_ARTH_OTHR_CLS_SPEC_value(dateOfTransplant);
                    break;
                case "Get_NEURO_AUTO_O_CLS_SPC_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_NEURO_AUTO_O_CLS_SPC_value(dateOfTransplant);
                    break;
                case "Get_CYTO_AUTO_O_CLS_SPC_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_CYTO_AUTO_O_CLS_SPC_value(dateOfTransplant);
                    break;
                case "Get_BWL_AUTO_O_CLS_SPEC_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_BWL_AUTO_O_CLS_SPEC_value(dateOfTransplant);
                    break;
                case "Get_SYS_SCD_INV_TYP_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_SYS_SCD_INV_TYP_value(dateOfTransplant);
                    break;
                case "Get_SYS_LUP_ERY_INV_TYP_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_SYS_LUP_ERY_INV_TYP_value(dateOfTransplant);
                    break;
                case "Get_SLE_OTR_ABDY_SPEC_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_SLE_OTR_ABDY_SPEC_value(dateOfTransplant);
                    break;
                case "Get_SJO_SYN_INV_TYP_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_SJO_SYN_INV_TYP_value(dateOfTransplant);
                    break;
                case "Get_HSCT_RSRCH_CNSNT_YN_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_HSCT_RSRCH_CNSNT_YN_value();
                    break;
                case "Get_RMAB_PRP_REG_TYPE_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_RMAB_PRP_REG_TYPE_value(dateOfTransplant);
                    break;
                case "Get_UNRLTD_DNR_REG_SPEC_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_UNRLTD_DNR_REG_SPEC_value(dateOfTransplant);
                    break;
                case "Get_MPS_POS_JAK2_AS_IND3_value":
                    dalAnwser = EbmtDAL.EbmtDAL.Get_MPS_POS_JAK2_AS_IND3_value(dateOfTransplant);
                    break;
                default: return myAnswer;
            }
            myAnswer.hasAResponse = dalAnwser.hasAResponse;
            myAnswer.freeTextEntry = dalAnwser.freeTextEntry;
            myAnswer.textAnswer = dalAnwser.textAnswer;
            return myAnswer;
        }



        #endregion

        #region Methods used to test the expressions of each ConditionId

        //This region contains methods used for the treatment of the Condition rows stored into the table
        //MappingConditions. When there is a group of conditions, we get first the value of each subgroup.
        //The value of each subgroup of conditions is retrieved using the GetConditionValue method.
        //Example : whe have a condition expresion like this: "((A AND B) OR (C AND D)) OR E"
        //Into the MappingConditions table this expression is going to be divided in groups like this:
        //Group 1 : (A AND B) OR (C AND D)
        //Group 2 : E
        //Also Group 1 will be divided in two subgroups like this:
        //subGroup 1: (A AND B)
        //subGroup 2: (C AND D)
        //Then GetGroupValue function is going to test the value of each Group (in the last example Group1 and 2).
        //This function is going to use the GetSubGroupValue in order to get the value of each of the subgroups.
        //In the previous example it will use this function to get the values of subgroups 1 and 2.
        //Then finally the GetSubGroupValue function is going to use the function GetConditionValue in order to get
        //the value of each condition in the subgroup.

        public TranslationAnswer GetResultOfTestingConditionIdExpressions(string conditionsId, DataRow valueRow, MappingDataSet.FieldValuesRow varRow, DataSet ebmtFilteredDataSet)
        {
            //When hasConditions its True we need to take the ConditionsID in order to look for the conditions,
            //in the MappingConditions table.
            TranslationAnswer myAnswer = new TranslationAnswer();
            DataView dvConditions = new DataView(dsMappingInfo.MappingConditions);
            DataView dvConGroups = new DataView(dsMappingInfo.ConditionGroupsList);
            dvConditions.RowFilter = "[EBMT Conditions ID]='" + conditionsId + "'";
            dvConGroups.RowFilter = "[EBMT Conditions ID]='" + conditionsId + "'";
            //We get the external operator used to link the groups.
            string externalGroupRelation = GetExternalGroupRelation(dvConditions);
            bool RelationResultAnd = true;
            bool RelationResultOr = false;
            for (int i = 1; i <= dvConGroups.Count; i++)
            {
                DataView groupConditions = new DataView(dsMappingInfo.MappingConditions);
                groupConditions.RowFilter = "[EBMT Conditions ID]='" + conditionsId
                                            + "' AND ConGroup='" + i + "'";
                //We test the value of the group and using the external operator we calculate the total result.
                if (externalGroupRelation == "AND")
                {
                    RelationResultAnd = RelationResultAnd && GetGroupValue(groupConditions, conditionsId, i, ebmtFilteredDataSet);
                }
                else if (externalGroupRelation == "OR")
                {
                    RelationResultAnd = false;
                    RelationResultOr = RelationResultOr
                        || GetGroupValue(groupConditions, conditionsId, i, ebmtFilteredDataSet);
                }
                else if (externalGroupRelation == "NONE")
                {
                    if (dvConGroups.Count == 1)
                    {
                        RelationResultAnd = RelationResultAnd && GetGroupValue(groupConditions, conditionsId, i, ebmtFilteredDataSet);
                    }
                    else
                    {
                        throw new TranslationException("The Conditions groups must have an external relationship operator.");
                    }
                }
            }
            if (RelationResultAnd || RelationResultOr)
            {
                myAnswer.hasAResponse = true;
                if (valueRow["Value Meaning Public ID"] != System.DBNull.Value)
                {
                    myAnswer.valueMeaningPublicId = (int)valueRow["Value Meaning Public ID"];
                }
                if (varRow["CopyEBMTValue"] != System.DBNull.Value)
                {
                    if (varRow.CopyEBMTValue == "No")
                    {
                        return myAnswer;
                    }
                    else
                    {
                        return CopyEbmtValue(varRow, ebmtFilteredDataSet);
                    }
                }
                else
                {
                    return myAnswer;
                }
            }
            else
            {
                myAnswer.hasAResponse = false;
                return myAnswer;
            }
        }

        private bool GetGroupValue(DataView groupConditions, string eBMT_Conditions_ID, int conGroup, DataSet ebmtFilteredDataSet)
        {
            bool RelationAndResult = true;
            bool RelationOrResult = false;
            

            DataView conSubGroups = new DataView(dsMappingInfo.ConditionsSubGroupsList);
            conSubGroups.RowFilter = "[EBMT Conditions ID]='" + eBMT_Conditions_ID + "' AND "
                                        + "ConGroup='" + conGroup + "'";
            if (conSubGroups.Count > 1)
            {
                //We need to calculate this group value using the subgroups values and GR_INREL1.
                for (int iSubGroup = 1; iSubGroup <= conSubGroups.Count; iSubGroup++)
                {
                    DataView subGroupsConditions = new DataView(dsMappingInfo.MappingConditions);
                    subGroupsConditions.RowFilter = "[EBMT Conditions ID]='" + eBMT_Conditions_ID +
                                                    "' AND ConGroup='" + conGroup +
                                                    "' AND ConSubGroup='" + iSubGroup + "'";
                    string firstInternalRelationship = subGroupsConditions[0]["GR_INREL1"].ToString();

                    if (firstInternalRelationship == "AND")
                    {
                        RelationAndResult = RelationAndResult && GetSubGroupValue(subGroupsConditions, ebmtFilteredDataSet);
                    }
                    else if (firstInternalRelationship == "OR")
                    {
                        RelationAndResult = false;
                        RelationOrResult = RelationOrResult || GetSubGroupValue(subGroupsConditions, ebmtFilteredDataSet);
                    }
                    else
                    {
                        throw new TranslationException("GR_INREL1 return an invalid value.");
                    }
                }
            }
            else if (conSubGroups.Count == 1)
            {
                //We need to calculate this group value using only one condition value.
                //CondSubGroup value in this case is 0 neal.
                DataView subGroupsConditions = new DataView(dsMappingInfo.MappingConditions);
                subGroupsConditions.RowFilter = "[EBMT Conditions ID]='" + eBMT_Conditions_ID +
                                                "' AND ConGroup='" + conGroup +
                                                "' AND ConSubGroup='0'";

                if (subGroupsConditions.Count == 1)
                {
                    //We need to calculate the value of this condition, using the external relationship.
                    string externalRelationship = subGroupsConditions[0]["GR_EXREL"].ToString();
                    MappingDataSet.MappingConditionsRow conRow = (MappingDataSet.MappingConditionsRow)subGroupsConditions[0].Row;
                    if (externalRelationship == "AND")
                    {
                        RelationAndResult = RelationAndResult && GetConditionValue(conRow, ebmtFilteredDataSet);
                    }
                    else if (externalRelationship == "OR")
                    {
                        RelationAndResult = false;
                        RelationOrResult = RelationOrResult || GetConditionValue(conRow, ebmtFilteredDataSet);
                    }
                    else if (externalRelationship == "NONE")
                    {
                        RelationAndResult = RelationAndResult && GetConditionValue(conRow, ebmtFilteredDataSet);
                    }
                }
                else
                {
                    throw new Exception();
                }
            }
            else
            {
                throw new Exception();
            }
            //**************************************************
            //When the group is related using an AND_Operator:
            //the instruction: return (RelationAndResult || RelationOrResult);
            //possible values:          True      ||       False   ->  True
            //possible values:          False     ||       False  ->  False
            //So in this case, this instruction is always going to return "true" if the RelationAndResult is True.
            //In the case RelationAndResult turns to False, then FALSE || FALSE will return False.
            //**************************************************
            //When the group is related with an OR_Operator:
            //the instruction: return (RelationAndResult || RelationOrResult);
            //possible values:          False      ||       True   ->  True
            //possible values:          False      ||       False  ->  False
            //is always going to return "true" if the RelationOrResult turns to True.
            //In the case the RelationOrResult stay False, then FALSE || FALSE will return False.
            //**************************************************
            return (RelationAndResult || RelationOrResult);
        }

        public bool GetSubGroupValue(DataView subGroupsConditions, DataSet ebmtFilteredDataSet)
        {
            bool RelationAndResult = true;
            bool RelationOrResult = false;

            if (subGroupsConditions.Count == 1)
            {
                //We need to calculate the value of this condition, using only GR_INREL1.
                string firstInternalRelationship = subGroupsConditions[0]["GR_INREL1"].ToString();
                MappingDataSet.MappingConditionsRow conRow = (MappingDataSet.MappingConditionsRow)subGroupsConditions[0].Row;
                if (firstInternalRelationship == "AND")
                {
                    RelationAndResult = RelationAndResult && GetConditionValue(conRow, ebmtFilteredDataSet);
                }
                else if (firstInternalRelationship == "OR")
                {
                    RelationAndResult = false;
                    RelationOrResult = RelationOrResult || GetConditionValue(conRow, ebmtFilteredDataSet);
                }
            }
            else if (subGroupsConditions.Count > 1)
            {
                bool secondRelationAndResult = true;
                bool secondRelationOrResult = false;
                bool secondRelationCombinedResult;
                //We need to calculate the value of each condition belonging to this subgroup, using GR_INREL1 externally,
                //and using GR_INREL2 internally.
                string firstInternalRelationship = subGroupsConditions[0]["GR_INREL1"].ToString();
                string secondInternalRelationship = subGroupsConditions[0]["GR_INREL2"].ToString();
                foreach (DataRowView rViewSubCondition in subGroupsConditions)
                {
                    MappingDataSet.MappingConditionsRow conRow = (MappingDataSet.MappingConditionsRow)rViewSubCondition.Row;
                    //We need to calculate the value of each condition belonging to this subgroup
                    //using the secondInternalRelationship as first step.
                    if (secondInternalRelationship == "AND")
                    {
                        secondRelationAndResult = secondRelationAndResult && GetConditionValue(conRow, ebmtFilteredDataSet);
                    }
                    else if (secondInternalRelationship == "OR")
                    {
                        secondRelationOrResult = secondRelationOrResult || GetConditionValue(conRow, ebmtFilteredDataSet);
                    }
                }
                if (secondInternalRelationship == "AND")
                {
                    secondRelationCombinedResult = true;
                    secondRelationCombinedResult = secondRelationCombinedResult && secondRelationAndResult;
                }
                else
                {
                    secondRelationCombinedResult = false;
                    secondRelationCombinedResult = secondRelationCombinedResult || secondRelationOrResult;
                }

                if (firstInternalRelationship == "AND")
                {
                    RelationAndResult = RelationAndResult && secondRelationCombinedResult;
                }
                else if (firstInternalRelationship == "OR")
                {
                    RelationAndResult = false;
                    RelationOrResult = RelationOrResult || secondRelationCombinedResult;
                }
            }
            //**************************************************
            //When the group is related using an AND_Operator:
            //the instruction: return (RelationAndResult || RelationOrResult);
            //possible values:          True      ||       False   ->  True
            //possible values:          False     ||       False  ->  False
            //So in this case, this instruction is always going to return "true" if the RelationAndResult is True.
            //In the case RelationAndResult turns to False, then FALSE || FALSE will return False.
            //**************************************************
            //When the group is related with an OR_Operator:
            //the instruction: return (RelationAndResult || RelationOrResult);
            //possible values:          False      ||       True   ->  True
            //possible values:          False      ||       False  ->  False
            //is always going to return "true" if the RelationOrResult turns to True.
            //In the case the RelationOrResult stay False, then FALSE || FALSE will return False.
            //**************************************************
            return (RelationAndResult || RelationOrResult);
        }

       

        private bool GetConditionValue(MappingDataSet.MappingConditionsRow mappingCondition, DataSet ebmtFilteredDataSet)
        {
            DataTable myDataTable = EbmtDAL.EbmtDAL.GetEBMTFilteredDataTable(mappingCondition, ebmtFilteredDataSet);
            string searchVal;
         
            if (mappingCondition["EBMT ConVar Value Code"] != System.DBNull.Value)
            {
                searchVal = mappingCondition.EBMT_ConVar_Value_Code.ToString();

            }
            else
            {
                searchVal = "NULL";
            }

            string comparisonOperator = mappingCondition.Operator;

            if (myDataTable != null)
            {
                if (myDataTable.Rows.Count > 0)
                {
                    for (int i = 0; i <= myDataTable.Rows.Count - 1; i++)
                    {
                        string oldValue="";

                        if (myDataTable.Rows[i][mappingCondition.EBMT_ConVar_ID] != System.DBNull.Value)
                        {
                            oldValue = myDataTable.Rows[i][mappingCondition.EBMT_ConVar_ID].ToString();
                            
                        }
                        else
                        {
                            if (searchVal == "NULL")
                            { 
                                oldValue = "NULL";
                                
                            }
                            else
                            {                                
                                //return false;     /* Desactivated by RRA */
                                /*RRA 18/10/2011 - bug report : when  an intermediate parameter's value from EBmt table is null, that skips the following ones (not null)*/
                            }
                        }
                       
                        if (myDataTable.Rows[i][mappingCondition.EBMT_ConVar_ID] != System.DBNull.Value) /* Added by RRA*/
                        {
                            switch (comparisonOperator)
                            {
                                case "==": if (oldValue == searchVal) return true; break;
                                case "<>": if (oldValue != searchVal) return true; break;
                                case ">": if (decimal.Parse(oldValue) > decimal.Parse(searchVal)) return true; break;
                                case "<": if (decimal.Parse(oldValue) < decimal.Parse(searchVal)) return true; break;
                                case "<=": if (decimal.Parse(oldValue) <= decimal.Parse(searchVal)) return true; break;
                                case ">=": if (decimal.Parse(oldValue) >= decimal.Parse(searchVal)) return true; break;
                                case "EXIST": return true;
                                case "NOT EXIST": return false;


                                default: return false;
                            }

                        }
                        
                            
                         
                    }
                    return false;
                }
                else
                {
                    switch (comparisonOperator)
                    {
                        case "EXIST": return false;
                        case "NOT EXIST": return true;
                        //Case when in the AgnisEBMTMappingDatabase in the table MappingConditions
                        //there is an operator different of EXIST or NOT EXIST that has not a valid comparing value.
                        default: return false;
                    }
                }
            }
            else
            {
                switch (comparisonOperator)
                {
                    case "EXIST": return false;
                    case "NOT EXIST": return true;
                    //Case when in the AgnisEBMTMappingDatabase in the table MappingConditions
                    //there is an operator different of EXIST or NOT EXIST that has not a valid comparing value.
                    default: return false;
                }
            }

        }

        public TranslationAnswer CopyEbmtValue(MappingDataSet.FieldValuesRow valueRow, DataSet ebmtFilteredDataSet)
        {
            TranslationAnswer myAnswer = new TranslationAnswer();
            string answerText = "";
            DataTable myDataTable = EbmtDAL.EbmtDAL.GetEBMTFilteredDataTable(valueRow.EBMT_Map_Table_ID, ebmtFilteredDataSet);
            if (myDataTable != null)
            {
                for (int i = 0; i <= myDataTable.Rows.Count - 1; i++)
                {
                    if (valueRow["EBMT MapVar WhatToCopy"] != null)
                    {
                        if (valueRow.EBMT_MapVar_WhatToCopy == "Value" || valueRow.EBMT_MapVar_WhatToCopy == "VALUE")
                        {
                            if (valueRow["Data type"] != null)
                            {
                                if (valueRow.Data_type == "DATE" || valueRow.Data_type == "Date")
                                {
                                    if (myDataTable.Rows[i][valueRow.EBMT_MapVar_ID] != System.DBNull.Value)
                                    {
                                        DateTime myDate = (DateTime)myDataTable.Rows[i][valueRow.EBMT_MapVar_ID];
                                        answerText = myDate.ToString("yyyy-MM-dd");
                                    }
                                }
                                else
                                {
                                    answerText = myDataTable.Rows[i][valueRow.EBMT_MapVar_ID].ToString();
                                }
                            }
                            else
                            {
                                answerText = myDataTable.Rows[i][valueRow.EBMT_MapVar_ID].ToString();
                            }
                        }
                        else
                        {
                            answerText = EbmtDAL.EbmtDAL.GetEBMTVariableValueDescription(valueRow.EBMT_MapVar_ID, (int)valueRow.EBMT_MapVar_Values_Group_ID, int.Parse(myDataTable.Rows[i][valueRow.EBMT_MapVar_ID].ToString()));
                        }
                    }
                    else
                    {
                        answerText = myDataTable.Rows[i][valueRow.EBMT_MapVar_ID].ToString();
                    }
                }
            }
            myAnswer.freeTextEntry = true;
            myAnswer.hasAResponse = true;
            myAnswer.textAnswer = answerText;
            return myAnswer;
        }

        public static string GetExternalGroupRelation(DataView dvConditions)
        {
            DataRowView myRowView = (DataRowView)dvConditions[0];
            MappingDataSet.MappingConditionsRow myRow = (MappingDataSet.MappingConditionsRow)myRowView.Row;
            return myRow.GR_EXREL;
        }

        #endregion
        #endregion

        #region XML related methods
        public static string SerializeObjectToXmlString(object obj)
        {
            XmlTextWriter writer = new XmlTextWriter(new MemoryStream(), Encoding.UTF8);
            writer.Formatting = Formatting.Indented;
            XmlSerializer serializer = new XmlSerializer(obj.GetType());
            serializer.Serialize(writer, obj);
            MemoryStream stream = (MemoryStream)writer.BaseStream;
            string xmlString = UTF8ByteArrayToString(stream.ToArray());
            return xmlString;
        }

        public static string UTF8ByteArrayToString(Byte[] characters)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            return encoding.GetString(characters);
        }
        #endregion

    }

    #endregion

}
